package ferp.center.server.servlet;

import ferp.center.network.RequestLeaderboardGet;
import ferp.center.network.ResponseLeaderboardGet;
import ferp.center.network.ResponseRating;
import ferp.center.server.Action;
import ferp.center.server.entity.Profile;
import ferp.center.server.entity.Rating;
import ferp.center.server.ranking.Ranker;
import ferp.center.server.task.TaskRangeTreeUpdate;
import ferp.core.Version;
import ferp.core.game.Settings;
import ferp.core.util.Convert;

import javax.persistence.EntityManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * User: igorgok
 * Date: 5/13/12 5:08 PM
 */
public class LeaderboardGet extends HttpServlet
{
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    Action.execute(request, response, RequestLeaderboardGet.class, new Action.Read<RequestLeaderboardGet, ResponseLeaderboardGet>()
    {
      @SuppressWarnings("unchecked")
      public ResponseLeaderboardGet run(EntityManager em, RequestLeaderboardGet input) throws IOException
      {
        ResponseLeaderboardGet result = new ResponseLeaderboardGet();

        if (input.version.code < Version.LATEST)
        {
          result.list.add(new ResponseRating("Your app version"));
          result.list.add(new ResponseRating(input.version.name + " is old."));
          result.list.add(new ResponseRating("Please update!"));
          result.list.add(new ResponseRating("--------------"));
          result.list.add(new ResponseRating("Версия вашего"));
          result.list.add(new ResponseRating("приложения"));
          result.list.add(new ResponseRating(input.version.name + " устарела."));
          result.list.add(new ResponseRating("Пожалуйста"));
          result.list.add(new ResponseRating("обновите!"));
        }
        else
          top10(em, input, result);

        return result;
      }
    });
  }

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}

  // todo: use the range tree instead of query
  private static void top10(EntityManager em, RequestLeaderboardGet input, ResponseLeaderboardGet result)
  {
    Profile p = null;
    Rating r = null;
    String configuration = Convert.configuration(input.configuration);
    List<List<Rating>> top = Ranker.top(em, configuration, 10);

    if (input.profile > 0)
    {
      // try to determine player's rank
      if ((p = em.find(Profile.class, input.profile)) != null)
      {
        if ((r = p.getRating(configuration)) != null)
          if (r.getRange() != null)
            result.rank = Ranker.rank(em, r);
          else
          {
            Action.logger().warning("rating for profile [" + input.profile + "]/[" + configuration + "] has no parent range");

            TaskRangeTreeUpdate.queue(r);
          }
        else
          Action.logger().warning("rating for configuration [" + configuration + "] not found for profile [" + p.getKey().getId() + "]");
      }
      else
        Action.logger().warning("profile [" + input.profile + "] not found");
    }

    // debug: add me to the first position
/*
    if (p != null && r != null)
    {
      List<List<Rating>> temp = new LinkedList<List<Rating>>();

      for (List<Rating> position : top)
      {
        List<Rating> list = new LinkedList<Rating>();

        list.addAll(position);
        temp.add(list);
      }

      temp.get(0).add(r);
      top = temp;

      result.rank = 1;
    }
*/

    if (top != null)
      for (List<Rating> position : top)
        result.list.add(convert(position, p, r));
  }

  private static String configuration(RequestLeaderboardGet input)
  {
    StringBuilder sb = new StringBuilder(input.configuration);

    // adjust configuration code
    if (input.version == null)
      sb.append(Settings.Level.L0.ordinal()).append(Settings.Level.L0.ordinal());

    return sb.toString();
  }

  private static ResponseRating convert(List<Rating> position, Profile profile, Rating rating)
  {
    ResponseRating result = new ResponseRating();

    //Action.logger().info("position size: " + position.size());

    if (position.size() > 0)
    {
      boolean in = false;

      // are we in the top 10?
      if (profile != null)
        for (Rating r : position)
          if (r.getProfile().getKey().equals(profile.getKey()))
          {
            in = true;
            break;
          }

      if (!in)
      {
        rating = position.get(0);
        profile = rating.getProfile();
      }

      result.profile = profile.getKey().getId();
      result.name = profile.getName();

      // show how many players are at the same position
      if (position.size() > 1)
        result.name += " +" + (position.size() - 1);

      result.games = rating.getGames();
      result.pool = rating.getPool();
      result.value = rating.calculate();
    }
    else
      result.name = "= empty =";

    return result;
  }
}
